import { BTState } from "./BTState";
import { BehaviorTree } from "./BehaviorTree";

/**
 * [行为树]节点基类
 * 所有行为树节点都由此类派生
 */
export abstract class BTNode<T = any> {

    private _tree: BehaviorTree<T>;
    /** 节点状态 */
    state = BTState.init;

    /** 所在树 */
    get tree() {
        return this._tree;
    }

    /**
     * 设置所在树
     * @param tree 
     */
    setTree(tree: BehaviorTree<T>) {
        this._tree = tree;
    }

    /** 
     * 标记节点流程结束
     * 下次重新执行任务时会先执行onStart
     */
    done() {
        this.state = BTState.init;
    }

    /**
     * 节点执行任务
     * @param ctx 行为树上下文
     * @returns 返回执行任务后的节点状态
     */
    abstract process(ctx: T): BTState

    /** 
     * 当节点开始执行任务前会调用一次
     * 直到父节点的所有子节点都完成流程之前都不会再调用
     * 在这里进行初始化操作
     * @param ctx 行为树上下文
     */
    protected onStart(ctx: T) { }

    /** 
     * 当节点状态从Run转变为其他状态时调用
     * 在这里进行清理操作
     * @param ctx 行为树上下文
     */
    protected onStop(ctx: T) { }

    /**
     * tick代表行为树运行一个周期
     * 从根节点开始逐层遍历节点 检测节点状态
     * @param ctx 行为树上下文
     */
    tick(ctx: T): BTState {

        if (this.state === BTState.init) {
            this.onStart(ctx);
        }

        this.state = this.process(ctx);

        if (this.state !== BTState.run) {
            this.onStop(ctx);
        }

        return this.state;
    }

}